package mn.more.wits.server.model;

import java.io.Serializable;
import java.util.ArrayList;
import javax.servlet.http.HttpSession;
import mn.more.wits.client.dto.ExamQuestionDTO;
import mn.more.wits.server.exception.AlreadyInExamSessionException;
import mn.more.wits.server.exception.ExamSessionException;

/**
 * to be stored in {@link HttpSession}.
 * <p/>
 * todo: needs more documentation! todo: needs i18n on messages/exceptions
 *
 * @author $Author: mikeliucc $
 * @version $Id: ExamSession.java 5 2008-09-01 12:08:42Z mikeliucc $
 */
public class ExamSession implements Serializable {

	/** the unique identifier associated with this test session */
	private String testId;
	private ExamTaker examTaker;
	/** start timee of this test session */
	private long startTime;
	/**
	 * stores the index of the latest question viewed by the <code>test
	 * taker</code>.
	 */
	private int lastQuestionSent;
	/**
	 * stores the timestamp of the latest question viewed by the <code>test
	 * taker</code>.
	 */
	private long lastQuestionSentTs;

	/** list of questions to be used for this test session. */
	private ArrayList<ExamQuestionDTO> questions = new ArrayList<ExamQuestionDTO>();
	/**
	 * stores <code>test taker</code>'s responses for this test session.  The
	 * actual flusing to database will occur at the end of a test session, or at
	 * the discretion of the server-side application.
	 */
	private ArrayList<ExamSessionResponse> responses = new ArrayList<ExamSessionResponse>();

	public String getTestId() { return testId; }

	public void setTestId(String testId) { this.testId = testId; }

	public WitsUser getTestTaker() { return examTaker; }

	/**
	 * associate an existing <code>test taker</code> with this test session. Such
	 * test taker must not be actively participating in another test.
	 */
	public void setTestTaker(ExamTaker examTaker) throws ExamSessionException {
		if (examTaker == null) { throw new NullPointerException("test taker cannot be null!"); }
		if (!examTaker.isValid()) { throw new ExamSessionException("invalid test taker found!"); }

		ExamSession examSession = examTaker.getCurrentTestSession();
		if (examSession != null) {
			throw new AlreadyInExamSessionException("test taker " + examTaker.getDisplayName() +
			                                        " is already participating in test session " +
			                                        examSession.getTestId());
		}

		this.examTaker = examTaker;
	}

	public long getStartTime() { return startTime; }

	public void setStartTime(long startTime) { this.startTime = startTime; }

	public int getLastQuestionSent() { return lastQuestionSent; }

	public void setLastQuestionSent(int lastQuestionSent) { this.lastQuestionSent = lastQuestionSent; }

	public long getLastQuestionSentTs() { return lastQuestionSentTs; }

	public void setLastQuestionSentTs(long lastQuestionSentTs) { this.lastQuestionSentTs = lastQuestionSentTs; }

	public ArrayList<ExamQuestionDTO> getQuestions() { return questions; }

	public ArrayList<ExamSessionResponse> getResponses() { return responses; }

}
